package org.tp8.sampleapp.loader.jobs;

import java.util.concurrent.ConcurrentHashMap;

import org.apache.log4j.Logger;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.tp8.sampleapp.loader.model.Case;

public abstract class AbstractTasklet <T extends Case>  implements Tasklet {
	
	/** The Constant log. */
	protected final static Logger log = Logger
			.getLogger(AbstractTasklet.class);
	
	/** The current case map. */
	@Autowired
	private ConcurrentHashMap<Long, T> currentCaseMap;
	
	/** The repeat status. */
	protected RepeatStatus repeatStatus;

	@Override
	public RepeatStatus execute(StepContribution contribution,
			ChunkContext chunkContext) {

		try {
			repeatStatus = executeTasklet(contribution, chunkContext);
		} catch (Exception exception) {
			repeatStatus = errorHandler(exception, contribution, chunkContext);
		}

		return repeatStatus;
	}

	/**
	 * Execute tasklet.
	 * 
	 * @param contribution
	 *            the contribution
	 * @param chunkContext
	 *            the chunk context
	 * @return the repeat status
	 * @throws Exception
	 *             the exception
	 */
	public abstract RepeatStatus executeTasklet(StepContribution contribution,
			ChunkContext chunkContext) throws Exception;

	/**
	 * Gets the current case.
	 * 
	 * @return the current case
	 */
	public T getCurrentCase() {
		return (T) currentCaseMap.get(Thread.currentThread().getId());
	}

	/**
	 * Sets the current case.
	 * 
	 * @param currentCase
	 *            the new current case
	 */
	public void setCurrentCase(T currentCase) {
		currentCaseMap.put(Thread.currentThread().getId(), currentCase);
	}

	/**
	 * Removes the current case.
	 * 
	 * @return the current case
	 */
	public void removeCurrentCase() {
		T t = getCurrentCase();
		currentCaseMap.remove(t);
	}

	/**
	 * Error handler.
	 * 
	 * @param exception
	 *            the exception
	 * @param contribution
	 *            the contribution
	 * @param chunkContext
	 *            the chunk context
	 */
	public RepeatStatus errorHandler(Exception exception,
			StepContribution contribution, ChunkContext chunkContext) {
		T migrationCase = getCurrentCase();
		if (migrationCase != null) {
			log.error("There was a problem with case " + migrationCase,
					exception);
		} else {
			log.error("Error during migration.", exception);
		}
		ExitStatus exitStatus = new ExitStatus("FAILED");
		contribution.setExitStatus(exitStatus);
		return RepeatStatus.FINISHED;

	}
}
